﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SceneManager.Processors
{
    public class SSAOProcessor : EffectProcessor
    {
        private static Random random = new Random();
        private static Texture2D randomTexture;
        private static Vector2 noiseScale;

        public int KernelSize { get; set; }
        public Vector3[] Kernel { get; private set; }

        public SSAOProcessor(Game game, int kernelSize) : base(game, "Shaders/SSAO/SSAO")
        {
            if (randomTexture == null)
            {
                randomTexture = Game.Content.Load<Texture2D>("Textures/Random4");
                noiseScale = new Vector2((float)Width / randomTexture.Width, (float)Height / randomTexture.Height);
            }

            // Kernel generation
            KernelSize = kernelSize;
            Kernel = new Vector3[KernelSize];
            for (int i = 0; i < KernelSize; i++)
            {
                Kernel[i] = new Vector3((float)random.NextDouble() * 2 - 1, (float)random.NextDouble() * 2 - 1, (float)random.NextDouble());
                Kernel[i].Normalize();

                float scale = (float)i / KernelSize;
                scale = MathHelper.Lerp(0.1f, 1.0f, scale * scale);
                Kernel[i] *= scale;
            }
        }

        public override void Process(Camera camera, GameTime gameTime)
        {
            Effect.Parameters["View"].SetValue(camera.View);
            Effect.Parameters["Projection"].SetValue(camera.Projection);

            Effect.Parameters["CameraPosition"].SetValue(camera.Position);
            Effect.Parameters["FrustumCorners"].SetValue(camera.FrustumCorners);
            Effect.Parameters["NoiseScale"].SetValue(noiseScale);
            Effect.Parameters["Kernel"].SetValue(Kernel);

            Effect.Parameters["RandomTexture"].SetValue(randomTexture);

            base.Process(camera, gameTime);
        }
    }
}
